/// 1. 模式是Rust中特殊的语法，模式用来匹配值的结构。
/// 2. 模式由如下内容组成：
/// - 字面值
/// - 解构的数组、枚举、结构体或者元组
/// - 变量
/// - 通配符
/// - 占位符
fn main() {
    // 1. match, 匹配时必须匹配完所有的情况，否则会报错，如下我只匹配0和1，就需要使用“_”下划线表示匹配所有
    let a = 1;
    match a {
        0 => {println!("zero: {}", a); }
        1 => {println!("one: {}", a); }
        _ => {println!("a: {}", a); }
    }
    // if let 语句
    let color: Option<&str> = None;
    let is_ok = false;
    let age: Result<u8, _> = "55".parse();
    if let Some(color) = color {
        println!("color: {}", color);
    } else if is_ok {
        println!("ok");
    } else if let Ok(age) = age {
        if age > 18 {
            println!("age: {}", age);
        } else {
            println!("age: {}, 是一个年轻的人", age);
        }
    } else {
        println!("in else");
    }

    // while let: 只要模式匹配就一直执行while循环
    let mut stack = Vec::new();
    stack.push(1);
    stack.push(2);
    stack.push(3);

    while let Some(top) = stack.pop() {
        println!("top: {}", top);
    } // 只要匹配Some(value)，就会一直循环

    // for：在循环中，模式是直接跟随for关键字的值，例如 for x in y，x就是对应的模式
    let v = vec!['a', 'b', 'c'];
    for (index, value) in v.iter().enumerate() {
        println!("index: {}, value: {}", index, value);
    } // 此处的模式是(index, value)

    // let语句
    let (x, y, z) = (1, 2, 3); // (1, 2, 3)会匹配(x, y, z)， 将1绑定到x，将2绑定到y，将3绑定到z
    println!("x: {}, y: {}, z: {}", x, y, z);
    let (x,.., z) = (1, 2, 3);
    println!("x: {}, z: {}", x, z);

    // 函数：函数的参数也是模式
    let po = (15, 20);
    print_point(&po);
    // 模式在使用它的地方并不都是相同的，模式存在不可反驳的和可反驳的


    //1、模式有两种：refutable（可反驳的）和 irrefutable（不可反驳的）。能匹配任何传递的可能值的模式被称为是不可反驳的。对值进行匹配可能会失败的模式被称为可反驳的。
    //2、只能接受不可反驳模式的有：函数、let语句、for循环。原因：因为通过不匹配的值程序无法进行有意义的工作。
    //3、if let和while let表达式被限制为只能接受可反驳的模式，因为它们的定义就是为了处理有可能失败的条件。
    let a: Option<i32> = Some(5); // 匹配Some(value)， None
    let b: Option<i32> = None; // 匹配Some(value)， None
    // let Some(x) = a;  // 这样匹配有问题
    if let Some(v) = a {
        println!("{}", v);
    }
}
fn print_point(&(x, y): &(i32, i32)) {
    println!("({},{})", x, y);
}
